RGoogleAnalytics <- function() {
  # Creates a skeleton shell for accessing the Google Analytics API.
  #
  # Returns:
  #   Returns a list of methods, for accessing the Google Analytics API.
  #           GetProfileData()       
  #           GetReportData()      
  #           GetAcctDataFeedJSON() 
  #	      GetProfilesFromJSON()  
  #	      ParseApiErrorMessage() 
  #	      ParseDataFeedJSON()    
  #	      kMaxDefaultRows()      
  # For more information please look at the help pages for each function.
  # Examples:
  # Step: 1. Authorize your account and paste the accesstoken 
  #    query <- QueryBuilder()
  #    access_token <- query$authorize()    						 
  # Step: 2. Create a new Google Analytics API object
  #	   ga <- RGoogleAnalytics()
  #    ga.profiles <- ga$GetProfileData(access_token)
  #    
  #    # To List the GA profiles 
  #    ga.profiles
  # Step: 3. Build the query string, use the profile by setting its index value 
  #    query$Init(start.date = "2011-06-18",
  #    end.date = "2012-12-18",
  #    dimensions = "ga:date, ga:pagePath",
  #    metrics = "ga:visits, ga:pageviews, ga:timeOnPage",
  #    sort = "ga:visits",
  #    #filters = "",
  #    #segment = "",
  #    max.results = 1012,
  #    table.id = paste("ga:", ga.profiles$id[1], sep="", collapse=","),
  #    access_token = access_token)
  # Step: 4. Make a request to get the data from the API
  #    ga.data <- ga$GetReportData(query)
  # Step: 5. Look at the returned data
  #    head(ga.data)

  # Constant 
  kMaxDefaultRows <- 10000 
  kMaxPages <- 100
  
  # We have used oauth 2.0 API to authorize the user account 
  # and to get the accesstoken to request to the Google Analytics Data API. 
  # The accesstoken is valid for 1 hour. 
  # A user needs to regenerate the accesstoken after one hour.
  query.uri <- NULL
  dataframe.param <- data.frame()

  # Set the curl options		
  options(RCurlOptions = list(capath = system.file("CurlSSL",
                                                   "cacert.pem", 
                                                   package = "RCurl"),
                             ssl.verifypeer = FALSE))
  
  ValidateToken <- function(access.token) {
    # This function will check whether the provided access_token is valid or 
    # expired. If it is a valid access token then it will return itself,
    # otherwise stop the execution.
    #  Args: 
    #    access.token: the token generated by Oauth 2.0 API to 
    #                  authorize the user account for Google Analytics 
    #                  data extraction.
    #  Returns: 
    #       access.token:
    api.response.json <- getURL(paste("https://www.googleapis.com/oauth2/v1/",
                                      "tokeninfo?access_token=",
                                      access.token,
                                      sep = "",
                                      collapse = ","))
    api.response.list <- fromJSON(api.response.json, method = 'C')	
    check.token.param <- regexpr("error", api.response.json)
    if (check.token.param[1] != -1) {
      stop(paste("Invalid/Expired access_token, regenerate",
                 "token by 'access_token <- query$authorize()'"))
    } else {
      return(access.token)
    }		
  }
  
  SetDataFrame <- function(GA.list.param.columnHeaders, dataframe.param) {
    # To prepare the dataframe by applying the column names and column datatypes 
    # to the provided data frame.
    #  Args:
    #    GA.list.param.columnHeaders: list includes GA reponse 
    #                                 data column name, column datatype.
    #    dataframe.param: The reponse data(dimensions and metrics data rows)
    #                     packed in dataframe without the column names and 
    #                     column types.
    # 
    #  Returns:
    #    dataframe.param : The dataframe attached with the column  names and 
    #    column datatype as per type the Dimnesions and metrics
  
    column.param <- t(sapply(GA.list.param.columnHeaders, 
     	                      '[',
                              1 : max(sapply(GA.list.param.columnHeaders,
                                             length))))
    col.name <- gsub('ga:', '', as.character(column.param[, 1]))
    col.datatype <- as.character(column.param[, 3])
    colnames(dataframe.param) <- col.name
			
    dataframe.param <- as.data.frame(dataframe.param)
    dataframe.param <- SetColDataType(col.datatype, col.name, dataframe.param)
						
    return(dataframe.param)
  }
			
  SetColDataType <- function(col.datatype, col.name, dataframe.param) {
    # This will set the appropriate data type to the each column of the 
    # provided dataframe.
    # Args: 
    #   col.datatype: The vector of the datatype of all the dimensions and 
    #                 metrics from the parsed list data.
    #   col.name:  The vector of the name of the all dimensions and metrics 
    #              of the retrived data and it will be attached to the 
    #              dataframe.param.
    # Returns:
    #   dataframe.param: The dataframe will be set with its column names with
    #   the appropriate class type.
    for(i in 1:length(col.datatype)) {
      if (col.datatype[i]=="STRING") {
        dataframe.param[, i] <- as.character(dataframe.param[, i]) 
      } else {
	dataframe.param[, i] <- as.numeric(as.character(dataframe.param[, i])) 
      }
    }
    return(dataframe.param)
  }
  
  GetProfilesFromJSON <- function(api.response.json) {
    # This function will do the parsing operation on the JSON reponse 
    # returned from the Google Management API and return the
    # dataframe stored with the profile id and prfile name
    # Args:
    #   api.reponse.json: The Json response from GetProfileData function 
    #                     which will request to the Google Management API.
    # Returns:
    #   Profileres.list: The list stored with totalResults as value of the 
    #                    total available data rows and profiles as the R 
    #                    dataframe object with two columns as column id and 
    #                    column name.			   
    GA.profiles <- ParseApiErrorMessage(api.response.json)
    TotalProfiles <- GA.profiles$totalResults
    if (!is.null(GA.profiles$code)) {
      stop(paste("code: ",
                 GA.profiles$code,
                 "Reason: ",
                 GA.profiles$message))
    }

    GA.profiles.param <- t(sapply(GA.profiles$items,
                           '[',
                           1 : max(sapply(GA.profiles$items, length)))) 
    profiles.id <- as.character(GA.profiles.param[, 1])
    profiles.name <- as.character(GA.profiles.param[, 7])
    if (length(profiles.id)==0) {
      stop("Please check the access token. It may be invalid or expired")
    } else {
      profiles <- data.frame(id=profiles.id,
                             name=profiles.name,
		             stringsAsFactors = FALSE)
      profileres.list <- list(totalResults = TotalProfiles,
                              profiles = profiles)
      return(profileres.list)     
    }
  }
  
  GetAcctDataFeedJSON <- function(query.uri) {
    # This function will make a request to the Google Management API with
    # the query prepared by the QueryBuilder() for retriving the GA Account
    # data. 
    # Args :
    #   query.uri: The data feed query strig generated by the Query builder 
    #              Class.
    # Returns :
    #   GA.Data: The response as account data feed in the JSON format.
    access_token <- ValidateToken(access_token)	
    GA.Data <- getURL(query.uri)
    return(GA.Data)
  }
  
  GetProfileData <- function(access_token) {
    # This function will retrive the available profiles from your 
    # Google anlaytics account by the Google Management API with the help of 
    # the access token. 
    # Args:	
    #   access_token: To authorize the user account.
    # Returns:
    #   profiles: R dataframe with profile id and profile name.
    query.uri <- paste('https://www.googleapis.com/analytics/v3/',
                       'management/accounts/~all/webproperties/~all/',
		       'profiles?access_token=',
                       access_token,
                       sep="", 
		       collapse = ",")
    if (!is.character(query.uri)) {
      stop("the query.uri parameter must be a character string")
    }
	
    # This api.reponse should be in json format
    api.response.json <- GetAcctDataFeedJSON(query.uri)
    profiles.param <- GetProfilesFromJSON(api.response.json)
    return(profiles.param$profiles)
  }
  
  ParseDataFeedJSON <- function(GA.Data) {
    # This function will parse the json response and checks if the reponse 
    # is contains an error, if found it will promt user with the related 
    # error message.
    # Args:
    #   GA.Data: The json reponse returned by the Google analytics Data 
    #            feed API. 
    # Returns:
    #    GA.list.param: GA.list.param list object obtained from this json 
    #                   argument GA.Data.
    GA.list.param <- ParseApiErrorMessage(GA.Data)
    if (!is.null(GA.list.param$code)) {
      stop(paste("code :",
                 GA.list.param$code,
                 "Reason :",
	         GA.list.param$message))
    }
    return(GA.list.param)
  }

  GetDataFeed <- function(query.uri) {
    # This will request with the prepared Query to the Google Analytics 
    # Data feed API and returns the data in dataframe R object.
    # Args: 
    #   query.uri: The URI prepared by the QueryBuilder class.
    # Returns:
    #   GA.DF: The dataframe stored with the dimensions and metrics 
    GA.Data <- getURL(paste(query.uri, sep = "", collapse = ","))	
    GA.list <- ParseDataFeedJSON(GA.Data)
    # For getting the total numbers of the data rows  
    total.results <-  GA.list$totalResults 
    if (is.null(GA.list$rows)) {
      print("Your query matched 0 results")
      break
    }
		
    if (length(query$dimensions()) == 0) {
      totalrows <- 1
      dataframe.param <- GA.list$rows[[1]]
      dim(dataframe.param) <- c(1, length(dataframe.param))
    } else {
      totalrows <- nrow(do.call(rbind, as.list(GA.list$rows)))
      dataframe.param <- rbind(dataframe.param, 
	                       do.call(rbind, as.list(GA.list$rows)))
    }
    GA.DF <- SetDataFrame(GA.list$columnHeaders, dataframe.param)
    return(list(total.results = total.results, data = GA.DF))
  }
  
  GetReportData <- function(query.builder, 
                            start.index = 1,
                            max.rows = NULL) {
    # This function will request with prepared query string to retrive the GA 
    # data feed in data.frame format. If the max.result term in the query is 
    # greater than 10000 then it will return the total available data from 
    # that profile by pagination otherwise it will return the data rows as per 
    # request either less than 10000 or less than 10000
    # Args : 
    #   query.uri: The data feed query string generated by the Query builder 
    #              Class.
    # Returns :
    #     api.response: The respose is in the dataframe format as the output 
    #                   data retruned from the Google Analytics Data feed API.

    query.builder$validate()
    # Ensure the starting index is set per the user request
    # We can only return 10,000 rows in a single query
    kMaxDefaultRows <- 10000
    max.rows <- query.builder$max.results()
    df <- GetDataFeed(query.builder$to.uri())

    if (df$total.results < kMaxDefaultRows) {
      max.rows <- kMaxDefaultRows
    }

    if (is.null(max.rows) || max.rows <= kMaxDefaultRows) {
     # No extra pagination is needed.
     print(paste("Your query matched",
                  nrow(df$data),
                 "results that are stored to dataframe ga.data"))
     return(df$data)
    } else {
      access_token <- ValidateToken(access_token)
    # Handle pagination. First get the number of pages needed. Then
    # update the start index for each page and request the data.
      pagination <- min(kMaxPages,
                        ceiling(df$total.results / kMaxDefaultRows))
      for (i in seq_along(2:pagination)) {
        start.index <- (i * kMaxDefaultRows) + 1
        query.builder$start.index(start.index)
        ga.data <- GetDataFeed(query.builder$to.uri())
        df$data <- rbind(df$data, ga.data$data)
        rm(ga.data)
      }
    print(paste("Your query matched",
	              nrow(df$data),
                "results that are stored to dataframe ga.data"))
    return(df$data)
    }
  }
  
  ParseApiErrorMessage <- function(api.response.json) {
    # To check whether the returned JSON response is error or not. 
    # If it is error then it will  
    # Args :  
    #   api.response.json: The json data as reposnse returned by the 
    #   Google Data feed API or Google Management API
    # Returns :
    #   If there is error in JSON response then this function will return the 
    #   related error code and message for that error.
    api.response.list <- fromJSON(api.response.json, method = 'C')	
    check.param <- regexpr("error", api.response.list)
    if (check.param[1] != -1) {
      return(list(code = api.response.list$error$code,
		  message = api.response.list$error$message))
    } else {
    code <- NULL
    return(api.response.list)
    }		
  }
  ##############################################################################

  return(list(GetProfileData       = GetProfileData,
              GetReportData        = GetReportData,
              GetAcctDataFeedJSON  = GetAcctDataFeedJSON,
              GetProfilesFromJSON  = GetProfilesFromJSON,
	      ParseApiErrorMessage = ParseApiErrorMessage,
	      ParseDataFeedJSON    = ParseDataFeedJSON,
	      kMaxDefaultRows      = kMaxDefaultRows)) 
}
